﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using JigLibX.Physics;
using JigLibX.Collision;
using JigLibX.Geometry;
using JigLibX.Math;
using Microsoft.Xna.Framework.Graphics;
using System.Xml;
using PloobsEngine.Utils;
using PloobsEngine.Modelo;

namespace PloobsEngine.Physics.XJigLib
{
    public class BoxObject : JigLibXObject
    {

        private Vector3 side = Vector3.One;
        private Vector3 fix = Vector3.Zero;       

    //   private BoundingBox GetBoundingBoxFromModel(ModelMesh[] model)
    // {         
    //  BoundingBox boundingBox = new BoundingBox();                

    //  foreach (ModelMesh mesh in model)
    //  {
    //    VertexPositionNormalTexture[] vertices =
    //      new VertexPositionNormalTexture[mesh.VertexBuffer.SizeInBytes / VertexPositionNormalTexture.SizeInBytes];

    //    mesh.VertexBuffer.GetData<VertexPositionNormalTexture>(vertices);
        
          
    //    Vector3[] vertexs = new Vector3[vertices.Length];

    //    for (int index = 0; index < vertexs.Length; index++)
    //    {
    //        vertexs[index] = vertices[index].Position;
    //    }

    //    boundingBox = BoundingBox.CreateMerged(boundingBox,
    //      BoundingBox.CreateFromPoints(vertexs));
    //  }
    //  //throw new Exception("Tem um BUg nesta funcao - esta criando um bounding box errado depois q eu alterei para usar meshparts - CONCERTAR URGENTEMENTE ");
    //  return boundingBox;
    //}

        /// <summary>
        /// Serialization
        /// </summary>
     public BoxObject()
     {
     }

     //public BoxObject(IModelo model, Vector3 position, Matrix orient, Vector3 scale,float mass)
     //    : this(model,position,orient,scale)
     //{
     //    this.Mass = mass;
     //}

     public override Vector3 Scale
     {
         get
         {
             return base.Scale;
         }
         set
         {
             this.scale = value;
             //CollisionSkin.ApplyLocalTransform(new Transform(Vector3.Zero, Matrix.CreateScale(value)));
             //throw new Exception("Not yet implement");
         }
     }
        
         
        //public BoxObject(IModelo model , Vector3 position , Matrix orient, Vector3 scale)
        //{            
        //    BoundingBox bb = new BoundingBox();            
        //    bb = BoundingBox.CreateMerged(bb,GetBoundingBoxFromModel(model));
            

        //    Vector3 side = new Vector3();
        //    side = (bb.Max - bb.Min);
        //    Vector3 s = new Vector3(side.X * scale.X, side.Y * scale.Y, side.Z * scale.Z);

        //    Body = new Body();
        //    CollisionSkin = new CollisionSkin(Body);
        //    CollisionSkin.AddPrimitive(new Box(s * 0.5f, Matrix.Identity, s), new MaterialProperties(0.8f, 0.8f, 0.7f));
        //    Body.CollisionSkin = this.CollisionSkin;
        //    Body.MoveTo(position , orient);
        //    Vector3 com = SetMass(5.0f);
        //    CollisionSkin.ApplyLocalTransform(new Transform(-com - Vector3.UnitZ * side.Z/4, Matrix.Identity));

        //    Body.DisableBody();
        //    this.Scale = s;
        //    this.side = side;
        //}

        public BoxObject(Vector3 sideLengths, Vector3 position, Matrix orientation, float mass)
            : this(sideLengths, position, orientation)
        {
            this.Mass = mass;
        }

        /// <summary>
        /// Cria um Bounding box normalmente porem aplica um deslocamento "correction" apenas no objeto fisico
        /// Server para ajustar modelos fisicos
        /// </summary>
        /// <param name="sideLengths"></param>
        /// <param name="position"></param>
        /// <param name="orientation"></param>
        /// <param name="correction"></param>
        public BoxObject(Vector3 sideLengths, Vector3 position, Matrix orientation, Vector3 correction,Matrix mcorrection)
        : this(sideLengths,position,orientation)
        {
            CollisionSkin.ApplyLocalTransform(new Transform(correction, mcorrection));
            this.fix = correction;
        }

        public BoxObject(Vector3 sideLengths, Vector3 position, Matrix orientation,Vector3 scale)
        {
            this.Init(sideLengths, position, orientation, Vector3.Zero, scale);
        }

        public BoxObject(Vector3 sideLengths, Vector3 position, Matrix orientation)
        {
            this.Init(sideLengths, position, orientation , Vector3.Zero,Vector3.One);
        
        }
        private void Init(Vector3 sideLengths, Vector3 position, Matrix orientation , Vector3 fix , Vector3 scale)
        {

            Vector3 s = new Vector3(sideLengths.X * scale.X, sideLengths.Y * scale.Y, sideLengths.Z * scale.Z);
            Body = new Body();
            CollisionSkin = new CollisionSkin(Body);
            CollisionSkin.AddPrimitive(new Box(s * 0.5f, Matrix.Identity, s), new MaterialProperties(0.8f, 0.8f, 0.7f));
            Body.CollisionSkin = this.CollisionSkin;
            Vector3 com = SetMass(1.0f);
            Body.MoveTo(position , orientation);
            CollisionSkin.ApplyLocalTransform(new Transform(-com , Matrix.Identity));
                        
            Body.DisableBody();
            this.Scale = scale;
            this.side = sideLengths;
            CollisionSkin.ApplyLocalTransform(new Transform(fix,Matrix.Identity));
            this.fix = fix;           
                        
            
        }



        public override void DeSerialize(XmlNode node, EngineStuff engine, IModelo model, Vector3 position, Matrix rotation)
        {            
            this.side = SerializerHelper.DeserializeVector3("SideLenght", node);
            this.fix = SerializerHelper.DeserializeVector3("Fix", node);
            Vector3 sc = SerializerHelper.DeserializeVector3("Scale", node);            
            Init(side, position,rotation , fix,sc);
            this.isMotionLess = SerializerHelper.DeserializeBaseType<bool>("CanMove", node);

        }

        public override void Serialize(System.Xml.XmlTextWriter textWriter)
        {
            SerializerHelper.SerializeVector3(Scale, "Scale", textWriter);
            SerializerHelper.SerializeBaseType<bool>(isMotionLess, "CanMove", textWriter);
            SerializerHelper.SerializeVector3(side, "SideLenght", textWriter);
            SerializerHelper.SerializeVector3(fix, "Fix", textWriter);            
        }
        public override PhysicObjectTypes PhysicObjectTypes
        {
            get { return PhysicObjectTypes.BOXOBJECT; }
        }

    
    }
}
